import Radio from 'backbone.radio';
import Validation from 'backbone-validation';
import {
    showLoader,
    setupDeferredExceptionHandling,
    setupAjaxCallbacks,
    setupAjaxCSRF
} from './tools.js';
import UserSession from 'base/components/UserSession.js';
import ConfigBus from 'base/components/ConfigBus.js';
import LoginApp from 'base/components/LoginApp.js';
import 'bootstrap/js/tab.js';


const showFieldSetError = function (control, error) {
    /*
    Show errors at fieldset level (used for error related to specific components)
    */
    var fieldset = control.closest('fieldset');
    fieldset.addClass('error');

    if (fieldset.find('.alert-danger').length === 0) {
        fieldset.find('.title').after(
            "<div class=\"alert alert-danger\"></div>"
        );
    }
    let fieldsetBlock = fieldset.find('.alert-danger');
    return fieldsetBlock.text(error);
}
const showFieldError = function (control, error) {
    /*
    Show an error at field level

    control

        The form field jquery object (input, select ...)
        We look for the parent form-group tag

    error

        The message as a string
   */
    var group = control.parents(".form-group");
    group.addClass("has-error");

    if (group.find(".help-block").length === 0) {
        group.append(
            "<span class=\"help-block error-message\"></span>"
        );
    }

    var groupBlock = group.find(".help-block");
    return groupBlock.text(error);
}

const hideFieldSetError = function (control) {
    /*
    Hide an error set with showFieldsetError
     */
    var fieldset = control.closest('fieldset');
    fieldset.removeClass('error');
    fieldset.find('.alert-danger').remove();
}
const hideFieldError = function (control) {
    /*
    Hide an error shown at field level
    */
    var group = control.parents(".form-group");
    group.removeClass("has-error");
    group.find(".error-message").remove();
    return control;
}

export const BootstrapOnValidForm = function (view, attr, selector) {
    console.log("BootstrapOnValidForm")
    var control, group;
    control = view.$('[' + selector + '=' + attr + ']');
    if (control.length === 0) {
        // Fallback looking for an item with attr css class
        control = view.$('.' + attr);
        hideFieldSetError(control);
    } else {
        hideFieldError(control);
    }
}

export const BootstrapOnInvalidForm = function (view, attr, error, selector) {
    var control, group, position, target;
    control = view.$('[' + selector + '=' + attr + ']');
    if (control.length === 0) {
        // Fallback looking for an item with attr css class
        control = view.$('.' + attr);
        showFieldSetError(control, error);
    } else {
        showFieldError(control, error);
    }
}

export const setupBbValidationCallbacks = function (bb_module) {
    _.extend(bb_module, {
        valid: BootstrapOnValidForm,
        invalid: BootstrapOnInvalidForm
    });
}

export const displayServerError = function (msg) {
    /*
     *  Show errors in a message box
     */
    let messagebus = Radio.channel('message');
    messagebus.trigger('error', msg);
}

export const displayServerSuccess = function (msg) {
    /*
     *  Show errors in a message box
     */
    let messagebus = Radio.channel('message');
    messagebus.trigger('success', msg);
}
require('jquery');
import _ from 'underscore';
import $ from 'jquery';

export const setupBbValidationPatterns = function (bb_module) {
    _.extend(bb_module.patterns, {
        amount: /^-?(\d+(?:[\.\,]\d{1,5})?)$/,
        amount2: /^(\d+(?:[\.\,]\d{1,2})?)$/,
        amount3: /^-?(\d+(?:[\.\,]\d{1,2})?)$/
    });
    _.extend(bb_module.messages, {
        amount: "Doit être un nombre avec au maximum 5 chiffres après la virgule",
        amount2: "Doit être un nombre positif avec au maximum 2 chiffres après la virgule",
        amount3: "Doit être un nombre avec au maximum 2 chiffres après la virgule"
    });
};

/**
 * Setup libraries on page load
 *
 *  - jquery exceptions (see setupDeferredExceptionHandling for details)
 *  - jquery ajax complete hook
 *  - Backbone.validation callbacks
 */
export const setupLibraries = function () {
    setupDeferredExceptionHandling();
    setupAjaxCallbacks();
    setupBbValidationCallbacks(Validation.callbacks);
    setupBbValidationPatterns(Validation);
}

/**
 * Backbone marionette application startup process in the new fashion
 *
 * @param {object} options : The AppOption global variable
 * @param {Mn.Application} app : The marionette application to start
 * @param {Object} facade : The facade radio channel used to manage model / collections interactions
 *
 * @param {Mn.App} actionsApp : Optionnal marionette application handling actions
 * @param {Mn.App} statusHistoryApp : Optionnal marionette application handling actions
 * @param {list} customServices: Optionnal radio channel services
 */

export const applicationStartup = function (
    options,
    app,
    facade,
    customOptions
) {
    customOptions = customOptions || {};
    const actionsApp = customOptions.actionsApp || null;
    const statusHistoryApp = customOptions.statusHistoryApp || null;
    const customServices = customOptions.customServices || [];
    console.log("# Booting Marionette/Backbone app v2 process");
    showLoader();
    setupLibraries();
    setupAjaxCSRF(options['csrf_token']);
    options.config = ConfigBus;
    options.login = LoginApp;
    options.app = app;
    options.facade = facade;
    options.actionsApp = actionsApp;
    options.statusHistoryApp = statusHistoryApp;
    options.$ = $;
    options.session = UserSession;

    ConfigBus.setup(options['form_config_url']);
    customServices.forEach(
        service => service.setup(options['form_config_url'])
    );
    facade.setup(options);
    const startApp = function () {
        console.log(" - Starting the Config component");
        let promise1 = ConfigBus.start();
        customServices.forEach(function (service) {
            console.log(" - Starting a Custom component");
            promise1 = promise1.then(service.start.bind(service));
        });
        console.log(" - Starting the Facade component")
        let promise2 = promise1.then(facade.start.bind(facade));

        promise2.done(
            function (result1, result2) {
                console.log("- Components started : Starting the application");
                if (app) {
                    app.start();
                }
                // L'application a démarré, désormais en callback de l'auth, on
                // veut synchroniser les modifications en cours
                LoginApp.setAuthCallbacks([facade.start.bind(facade)]);
                if (actionsApp) {
                    actionsApp.start(ConfigBus.form_config['actions']);
                }
                if (statusHistoryApp) {
                    statusHistoryApp.start(facade.getCollectionRequest('status_history'))
                }
            }
        );
    }


    // Au cas où on échoue lors du premier chargement, on veut pouvoir re
    // lancer la page après authentification
    LoginApp.setAuthCallbacks(
        [startApp]
    );
    LoginApp.start();
}

/**
 * Utility used to hide a region and its content
 * @param {Mn.Region} region : The Marionettejs Region instance (this.getRegion('regionName') from inside a View)
 *
 */
export const hideRegion = function (region) {
    // Remove subview if there is one
    if (region.hasView()) {
        region.empty();
    }
    // Hide the region container
    // Afin de s'assurer que nous travaillons bien sur le tag de la Region
    // et pas un autre dans la page, on repart du parent de la Region
    // region.$el pointe parfois au mauvais endroit (pour une raison inconnue)
    const parentEl = _.result(region, 'parentEl');
    const regionTag = $(parentEl).find(region.el);
    regionTag.hide();
}

/**
 * Utility used to show a region (if it has been hidden)
 * @param {Mn.Region} region : The Marionettejs Region instance (this.getRegion('regionName') from inside a View)
 *
 */
export const showRegion = function (region) {
    region.$el.show();
}


export const bindModelValidation = function (model) {
    Object.assign(model, Validation.mixin);
}

export const unbindModelValidation = function (model) {
    delete model.validate;
    delete model.preValidate;
    delete model.isValid;
}
